import org.virtualbox_4_1.AccessMode;
import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.DeviceType;
import org.virtualbox_4_1.IConsole;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IMedium;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.ISnapshot;
import org.virtualbox_4_1.IVirtualBox;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.StorageBus;
import org.virtualbox_4_1.VBoxException;
import org.virtualbox_4_1.VirtualBoxManager;

public class VBoxUtils {

	static IMachine create(VirtualBoxManager mgr, IVirtualBox vbox, ISession session) {
		System.out.println("\nAttempting to create VM");
		IMachine machine = vbox.createMachine(null, "telles", "Ubuntu",
				"00000000-0000-0000-0000-000000000000", false);
		machine.addStorageController("diskAttachment", StorageBus.IDE);
		machine.lockMachine(session, LockType.Shared);
		IMachine mutable = session.getMachine();
		IMedium medium = vbox.openMedium("/home/tellesmvn/og-image.vdi",
				DeviceType.HardDisk, AccessMode.ReadWrite, true);
		mutable.attachDevice("diskAttachment", 0, 0, DeviceType.HardDisk,
				medium);
		machine.saveSettings();
		session.unlockMachine();

		vbox.registerMachine(machine);

		return machine;

	}

	static IMachine findMachine(IVirtualBox vbox) {
		return vbox.findMachine("telles");

	}

	static void delete(IMachine machine, ISession session) {
		System.out.println("\nAttempting to delete VM");
		
		machine.lockMachine(session, LockType.Write);
		IMachine mutable = session.getMachine();
		mutable.removeStorageController("diskAttachment");
		mutable.saveSettings();
		session.unlockMachine();

		machine.delete(machine.unregister(CleanupMode.Full));
	}

	static void start(ISession session, IMachine machine, IVirtualBox vbox) {
		System.out.println("\nAttempting to start VM");

		IProgress prog = machine.launchVMProcess(session, "gui", "");
		
		// -1 = Esperar até ação ser concluída
		prog.waitForCompletion(-1);
		if (prog.getResultCode() != 0) {
			System.out.println("Cannot launch VM!");
		}
		session.unlockMachine();
	}

	
	//Não Funciona
	static void takeSnapshot(ISession session, IMachine machine) {
		System.out.println("Attempting to take snapshot from vm");

		machine.lockMachine(session, LockType.Shared);
		IConsole console = session.getConsole();

		String nome = session.getMachine().getName() + "snapshot1";
		IProgress takeSnapshotProg = console.takeSnapshot(nome, "");

		takeSnapshotProg.waitForCompletion(-1);
		if (takeSnapshotProg.getResultCode() != 0) {
			System.out.println("Cannot take snapshot from VM");
		}
		
		session.unlockMachine();
	}

	static void createSharedFolder(ISession session, IMachine machine) {
		machine.lockMachine(session, LockType.Shared);
		IMachine mutable = session.getMachine();
		mutable.createSharedFolder("/tmp", "/tmp/playpen", true, true);
		mutable.saveSettings();
		session.unlockMachine();
	}
	
	static void restoreSnapshot(ISession session, IMachine machine) {
		System.out.println("Attempting to restore snapshot from vm");
		
		machine.lockMachine(session, LockType.Shared);
		IConsole console = session.getConsole();

		IProgress restoreSnapshotProg = console.restoreSnapshot(machine
				.getCurrentSnapshot());

		restoreSnapshotProg.waitForCompletion(-1);
		if (restoreSnapshotProg.getResultCode() != 0) {
			System.out.println("Cannot restore snapshot from VM");
		}
		session.unlockMachine();
	}

	static void stop(ISession session, IMachine machine) {
		System.out.println("Attempting to stop vm");

		machine.lockMachine(session, LockType.Shared);
		IConsole console = session.getConsole();

		IProgress shutDownProg = console.powerDown();
		shutDownProg.waitForCompletion(-1);
		if (shutDownProg.getResultCode() != 0) {
			System.out.println("Cannot stop VM");
		}

		IMachine mutable = session.getMachine();
		mutable.detachDevice("diskAttachment", 0, 0);
		mutable.saveSettings();
		session.unlockMachine();

	}

	static ISnapshot existSnapshot(IMachine machine) {
		try {
			ISnapshot snapshot = machine.getCurrentSnapshot();
			return snapshot;
		} catch (Exception e) {
			System.out.println("Não existe snapshot");
			return null;
		}
	}

	public static void main(String[] args) {

		VirtualBoxManager mgr = VirtualBoxManager.createInstance(null);

		try {
			IVirtualBox vbox = mgr.getVBox();
			ISession session = mgr.getSessionObject();
			if (vbox != null) {
//				IMachine machine = create(mgr, vbox);
				IMachine machine = findMachine(vbox);
//				createSharedFolder(session, machine);
				
//				try {
//					Thread.sleep(10000);
//				} catch (InterruptedException e) {
//					// TODO Auto-generated catch block
//					e.printStackTrace();
//				}
//				delete(machine, session);
				ISnapshot snapshot = existSnapshot(machine);
				if (snapshot == null) {
					takeSnapshot(session, machine);
				} else {
					restoreSnapshot(session, machine);
				}
				
				start(session, machine, vbox);
				try {
					Thread.sleep(100000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				stop(session, machine);
				// testEvents(mgr, vbox.getEventSource());
				// delete(machine,session);

				System.out.println("done, press Enter...");
				// int ch = System.in.read();
			}
		} catch (VBoxException e) {
			System.out.println("VBox error: " + e.getMessage() + " original="
					+ e.getWrapped());
			e.printStackTrace();
		}
	}
}
